/**
* JSON 工具包
*/

#define _CRT_SECURE_NO_WARNINGS
#include <stdlib.h>
#include <string.h>

#include "cccompat.h"
#include "json_utils.h"
#include "pcre2_regexp.h"

#include "log.h"
#define LOGLEVEL LOG_DEBUG
#define LOGTAG   "JSON-UTILS"
#include "log4app.h"

const char* json_get_field_raw(const char* json, const char* field) {
	if (!json || !field) return NULL;
	char buf[JSON_VALUE_SIZE_MAX];
	snprintf(buf, sizeof(buf), "\"%s\":([^,}]+)", field);
	return regexp_capture1(json, 0, buf);
}

const char* json_get_field_array_raw(const char* json, const char* field, size_t *count) {
	if (!json || !field) return NULL;
	char buf[JSON_VALUE_SIZE_MAX];
	snprintf(buf, sizeof(buf), "\"%s\":\\[([^\\]]+)\\]", field);
	const char* str = regexp_capture1(json, 0, buf);
    const char* str2 = str;
    if(str2 && count) {
		*count = 1;
        for(; *str2; str2++) {
            if(*str2 == ',') (*count)++;
		}
	}
	return str;
}

const char** json_get_string_array(const char* json, size_t max_count) {
	if (!json || !max_count) return NULL;
	char ch;
	size_t strlen = 0, count = 0;
	char **arr = (char**)malloc(sizeof(void*) * (max_count + 1));
	if(!arr) return NULL;
	memset(arr, 0, sizeof(void*) * (max_count + 1));

	for(const char *ps = NULL; (ch = *json); json++) {
		if(!ps) {
			if(ch == '\"') { ps = json + 1; strlen = 0; }
		} else {
			if(ch == '\"') {
				char *str = malloc(strlen + 1);
				strncpy(str, ps, strlen);
				str[strlen] = '\0';
				arr[count++] = str;
				if(count >= max_count) break;
				ps = NULL;
			} else {
				strlen++;
			}
		}
	}
	return (const char**)arr;
}

size_t json_get_int_array(const char* str, int *arr, size_t count) {
	if (!str || !arr || !count) return 0;
	size_t rc = 0;
	while(1) {
		int ret = sscanf(str, "%d", arr + rc); if (ret < 1) break;
        rc++;
        str = strchr(str, ','); if(!str) break;
		str++;
	}
	return rc;
}

size_t json_get_long_array(const char* str, long *arr, size_t count) {
	if (!str || !arr || !count) return 0;
	size_t rc = 0;
	while(1) {
		int ret = sscanf(str, "%ld", arr + rc); if (ret < 1) break;
		str = strchr(str, ','); if (!str) break;
		str++; rc++;
	}
	return rc;
}

size_t json_get_float_array(const char* str, float *arr, size_t count) {
	if (!str || !arr || !count) return 0;
	size_t rc = 0;
	while(1) {
		int ret = sscanf(str, "%f", arr + rc); if (ret < 1) break;
		str = strchr(str, ','); if (!str) break;
		str++; rc++;
	}
	return rc;
}

size_t json_get_double_array(const char* str, double *arr, size_t count) {
	if (!str || !arr || !count) return 0;
	size_t rc = 0;
	while(1) {
		int ret = sscanf(str, "%lf", arr + rc); if (ret < 1) break;
		str = strchr(str, ','); if (!str) break;
		str++; rc++;
	}
	return rc;
}

const char* json_get_field_string(const char* json, const char* field) { 
	if (!json || !field) return NULL;
	char buf[JSON_VALUE_SIZE_MAX];
	snprintf(buf, sizeof(buf), "\"%s\":\"([^\"]+)", field);
	return regexp_capture1(json, 0, buf);
}

std_err_t json_get_field_int(const char* json, const char* field, int* value) { 
	if (!json || !field || !value) return STD_ERR_INVALID_ARG;                   
	const char* str = json_get_field_raw(json, field);							 
	if (!str) return STD_ERR_NOT_FOUND;											 
	if (1 != sscanf(str, "%d", value)) return STD_ERR_ILLEGAL_CHAR;
	return STD_ERR_OK;
}

std_err_t json_get_field_long(const char* json, const char* field, long* value) {
	if (!json || !field || !value) return STD_ERR_INVALID_ARG;
	const char* str = json_get_field_raw(json, field);
	if (!str) return STD_ERR_NOT_FOUND;
	if (1 != sscanf(str, "%ld", value)) return STD_ERR_ILLEGAL_CHAR;
	return STD_ERR_OK;
}

std_err_t json_get_field_int64(const char* json, const char* field, int64_t* value) {
	if (!json || !field || !value) return STD_ERR_INVALID_ARG;
	const char* str = json_get_field_raw(json, field);
	if (!str) return STD_ERR_NOT_FOUND;
	if (1 != sscanf(str, "%lld", (FMTLLD*)value)) return STD_ERR_ILLEGAL_CHAR;
	return STD_ERR_OK;
}

std_err_t json_get_field_float(const char* json, const char* field, float* value) {
	if (!json || !field || !value) return STD_ERR_INVALID_ARG;
	const char* str = json_get_field_raw(json, field);
	if (!str) return STD_ERR_NOT_FOUND;
	if (1 != sscanf(str, "%f", value)) return STD_ERR_ILLEGAL_CHAR;
	return STD_ERR_OK;
}

std_err_t json_get_field_double(const char* json, const char* field, double* value) {
	if (!json || !field || !value) return STD_ERR_INVALID_ARG;
	const char* str = json_get_field_raw(json, field);
	if (!str) return STD_ERR_NOT_FOUND;
	if (1 != sscanf(str, "%lf", value)) return STD_ERR_ILLEGAL_CHAR;
	return STD_ERR_OK;
}
